package com.ddone;


import com.ddone.bean.User;
import com.ddone.mapper.UserEsRepository;
import net.datafaker.Faker;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.GetQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import javax.annotation.Resource;
import java.util.List;
import java.util.Locale;
import java.util.Optional;

/**
 * @author ddone
 * @date 2024/4/9-12:36
 */
@SpringBootTest
public class EsDemoTest {

    @Autowired
    private ElasticsearchRestTemplate esTemplate;

    @Resource
    private RestHighLevelClient esHighLevelClient;


    private Faker faker;

    @Resource
    private UserEsRepository userEsRepository;

    // @Before
    // private void  init(){
    //     // System.out.println(esTemplate);
    //     // System.out.println(esHighLevelClient);
    //     faker = new Faker(Locale.CHINA);
    // }

    @Test
    public void contextLoads(){
       // 创建索引 put /user
        IndexOperations userIndexOps = esTemplate.indexOps(User.class);
        if(!userIndexOps.exists()){
            userIndexOps.create();
            // put /user/_mapping {}
            userIndexOps.putMapping(userIndexOps.createMapping());
        }
    }

    @Test
    public void save(){
        // User user = User
        //         .builder()
        //         .name("王五")
        //         .age(20)
        //         .pwd("wangwu@126.com")
        //         .id(1L)
        //         .build();
        // esTemplate.save(user);
        faker = new Faker(Locale.CHINA);
        for (int i = 0; i < 100; i++) {
            User user = User
                    .builder()
                    .name(faker.name().name())
                    .age(faker.number().numberBetween(16,100))
                    .pwd(faker.phoneNumber().cellPhone())
                    .id(Long.valueOf(i+""))
                    .build();
            esTemplate.save(user);
        }
    }

    // 根据ID查询文档
    @Test
    public void getById(){
        User user = esTemplate.queryForObject(GetQuery.getById("1"), User.class);
        System.out.println(user);
    }

    // 查询所有
    @Test
    public void testMatchAll(){
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withQuery(QueryBuilders.matchAllQuery());
        SearchHits<User> search = esTemplate.search(builder.build(), User.class);
        List<SearchHit<User>> searchHits = search.getSearchHits();
        searchHits.forEach(s -> {
            User user = s.getContent();
            String id = s.getId();
            System.out.println("user = " + user);
            System.out.println("id = " + id);
        });
    }

    // 匹配查询
    @Test
    public void testMatch(){
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withQuery(QueryBuilders.matchQuery("name","锦"));
        SearchHits<User> searchHits = esTemplate.search(builder.build(), User.class);
        searchHits.forEach(hit -> System.out.println(hit.getContent()));
    }

    // 过滤查询,布尔查询
    @Test
    public void testBoolFilter(){
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withQuery(
                QueryBuilders.boolQuery()
                        .must(QueryBuilders.matchQuery("name","程"))
                        .filter(QueryBuilders.rangeQuery("age").gte("22").lte(100)));
        SearchHits<User> hits = esTemplate.search(builder.build(), User.class);
        System.out.println(hits.getTotalHits());
        hits.forEach(hit-> System.out.println(hit.getContent()));
    }

    // 复杂查询
    @Test
    public void testComplexQuery(){
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        // 放入搜索条件
        builder.withQuery(QueryBuilders.matchQuery("name","立"));
        // 放入年龄的过滤条件
        builder.withFilter(QueryBuilders.rangeQuery("age").gte(15));
        // 放入排序条件
        builder.withSort(SortBuilders.fieldSort("age").order(SortOrder.DESC));
        // 分页
        builder.withPageable(PageRequest.of(0,5));
        // 高亮
        builder.withHighlightBuilder(new HighlightBuilder().field("name").preTags("<em>").postTags("</em>"));
        // 聚合条件
        builder.addAggregation(AggregationBuilders.terms("pwdAgg").field("pwd"));
        builder.withFields("name","age");
        // 打印查询语句
        System.out.println(builder.build().getQuery().toString());
        //执行查询操作
        SearchHits<User> hits = esTemplate.search(builder.build(), User.class);
        hits.forEach(s -> System.out.println(s.getContent()));

        Aggregations aggregations = hits.getAggregations();
        assert aggregations != null;
        ParsedStringTerms pwdAgg = aggregations.get("pwdAgg");
        pwdAgg.getBuckets().forEach(b -> {
            System.out.println(b.getKeyAsString());
            System.out.println(b.getDocCount());
        });
    }

    @Test
    public void testMapperAdd(){
        faker = new Faker(Locale.CHINA);
        User user = User
                .builder()
                .name(faker.name().name())
                .age(faker.number().numberBetween(20,60))
                .pwd(faker.phoneNumber().cellPhone())
                .id(Long.valueOf(faker.number().numberBetween(1000,100000)+""))
                .build();
        System.out.println("user = " + user);
        userEsRepository.save(user);
    }

    @Test
    public void testDelete(){
        userEsRepository.deleteById(43200L);
    }

    @Test
    public void testQuery(){

        Optional<User> user = userEsRepository.findById(23204L);
        System.out.println(user.get());
    }

    @Test
    public void testOtherQuery(){
        // userEsRepository.findAll()
        List<User> users = userEsRepository.findByAgeBetween(10, 30);
        users.forEach(System.out::println);
    }

    @Test
    public void testQueryAnnotation(){
        List<User> users = userEsRepository.queryByName("甄靖琪");
        users.forEach(System.out::println);
    }
}
